package com.budwk.app.enterprise.services.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.budwk.app.base.utils.StrUtil;
import com.budwk.app.domain.vo.IncomeStatementVo;
import com.budwk.app.enterprise.component.IncomeStatementComponent;
import com.budwk.app.enterprise.models.BusinessInformation;
import com.budwk.app.enterprise.models.IncomeStatementBase;
import com.budwk.app.enterprise.models.IncomeStatementBaseDetail;
import com.budwk.app.enterprise.services.BusinessinformationService;
import com.budwk.app.enterprise.services.IncomeStatementBaseDetailService;
import com.budwk.app.enterprise.services.IncomeStatementBaseService;
import com.budwk.app.exception.AppException;
import com.budwk.app.miniapp.utils.StringUtils;
import com.budwk.starter.common.page.PageUtil;
import com.budwk.starter.common.page.Pagination;
import com.budwk.starter.database.service.BaseServiceImpl;
import com.budwk.starter.security.utils.SecurityUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.QueryResult;
import org.nutz.dao.entity.Record;
import org.nutz.dao.impl.FileSqlManager;
import org.nutz.dao.impl.NutDao;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@IocBean(args = {"refer:dao"})
@Slf4j
public class IncomeStatementBaseServiceImpl extends BaseServiceImpl<IncomeStatementBase> implements IncomeStatementBaseService {
    public IncomeStatementBaseServiceImpl(Dao dao) {
        super(dao);
        // 加载配置文件
        ((NutDao)dao).setSqlManager(new FileSqlManager("db/sqls/incomeStatementBase.sql"));
    }

    @Inject
    private IncomeStatementComponent incomeStatementComponent;
    @Inject
    private BusinessinformationService businessinformationService;
    @Inject
    private IncomeStatementBaseDetailService incomeStatementBaseDetailService;

    @Override
    public Pagination listByPage(IncomeStatementVo bean) {
        // 1 或者查询sql
        Sql sql = dao().sqls().create("listByPage");
        // 2 组装查询条件
        Cnd cnd = Cnd.NEW();
        cnd.where().andEquals(IncomeStatementBase::getIsDelete, false);
        if (StringUtils.isNotEmpty(bean.getCompanyName())) {
            cnd.and("b.company_name", "like", "%" + bean.getCompanyName() + "%");
        }
        if (bean.getFillType() != null) {
            cnd.and("a.fill_type", "=", bean.getFillType());
        }
        if (bean.getFillYear() != null) {
            cnd.and("a.fill_year", "=", bean.getFillYear());
        }
        if (bean.getFillValue() != null) {
            cnd.and("a.fill_value", "=", bean.getFillValue());
        }
        sql.setCondition(cnd);
        // 3 分页查询
        Pagination pagination = listPage(bean.getPageNo(), bean.getPageSize(), sql);
        pagination.setList(pagination.getList(IncomeStatementVo.class));
        return pagination;
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    public IncomeStatementVo create(IncomeStatementVo statementVo) {
        // 基本入参校验
        incomeStatementComponent.checkAddParam(statementVo);
        // 计算
        incomeStatementComponent.cal(statementVo);
        // 1 入库基本信息表
        IncomeStatementBase base = new IncomeStatementBase();
        BeanUtil.copyProperties(statementVo, base);
        base.setCreatedAt(LocalDateTime.now()).setCreatedBy(SecurityUtil.getUserId()).setUpdatedAt(LocalDateTime.now()).setUpdatedBy(SecurityUtil.getUserId());
        base.setId(StrUtil.getSnowId()).setIsDelete(false);
        this.insert(base);
        // 2 入库详情表
        IncomeStatementBaseDetail detail = new IncomeStatementBaseDetail();
        BeanUtil.copyProperties(statementVo, detail);
        detail.setCreatedAt(LocalDateTime.now()).setCreatedBy(SecurityUtil.getUserId()).setUpdatedAt(LocalDateTime.now())
                .setUpdatedBy(SecurityUtil.getUserId()).setIsDelete(false);
        detail.setIncomeStatementBaseId(base.getId());
        incomeStatementBaseDetailService.insert(detail);
        return statementVo;
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    public IncomeStatementVo updateData(IncomeStatementVo statementVo) {
        // 1 校验
        incomeStatementComponent.checkUpdateParam(statementVo);
        // 2 业务代码实现
        IncomeStatementBase statementBase = this.fetch(statementVo.getId());
        if (statementBase == null) {
            throw new AppException("数据不存在！");
        }
        incomeStatementComponent.cal(statementVo);
        IncomeStatementBase base = new IncomeStatementBase();
        BeanUtil.copyProperties(statementVo, base);
        base.setUpdatedAt(LocalDateTime.now()).setUpdatedBy(SecurityUtil.getUserId());
        this.updateIgnoreNull(base);
        // 2 入库详情表
        IncomeStatementBaseDetail detail = new IncomeStatementBaseDetail();
        BeanUtil.copyProperties(statementVo, detail);
        detail.setUpdatedAt(LocalDateTime.now()).setUpdatedBy(SecurityUtil.getUserId());
        detail.setIncomeStatementBaseId(base.getId());
        incomeStatementBaseDetailService.updateIgnoreNull(detail);
        return statementVo;
    }

    @Override
    public IncomeStatementVo getData(String id) {
        IncomeStatementVo vo = new IncomeStatementVo();
        IncomeStatementBase base = this.fetch(id);
        log.info("incomeStatementlService getData baseinfo res: {}", JSONObject.toJSONString(base));
        if (base == null) {
            return vo;
        }
        BeanUtil.copyProperties(base, vo);
        IncomeStatementBaseDetail detail = incomeStatementBaseDetailService.fetch(Cnd.where(IncomeStatementBaseDetail::getIncomeStatementBaseId, "=", base.getId()));
        log.info("incomeStatementlService getData detail res: {}", JSONObject.toJSONString(detail));
        BeanUtil.copyProperties(detail, vo);
        // 查询公司名称
        BusinessInformation information = businessinformationService.fetch(base.getCompanyId());
        vo.setCompanyName(information.getCompanyName())
                .setBusinessInformation(information)
                .setId(base.getId());
        log.info("incomeStatementlService getData IncomeStatementVo res: {}", JSONObject.toJSONString(vo));
        return vo;
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    public void deleteById(String id) {
        IncomeStatementBase base = this.fetch(id);
        if (base == null) {
            throw new AppException("未查询到任何数据！");
        }
        base.setIsDelete(true).setUpdatedBy(SecurityUtil.getUserId()).setUpdatedAt(LocalDateTime.now());
        this.updateIgnoreNull(base);
        IncomeStatementBaseDetail detail = incomeStatementBaseDetailService.fetch(Cnd.where(IncomeStatementBaseDetail::getIncomeStatementBaseId, "=", base.getId()));
        detail.setIsDelete(true).setUpdatedBy(SecurityUtil.getUserId()).setUpdatedAt(LocalDateTime.now());
        incomeStatementBaseDetailService.updateIgnoreNull(detail);
    }

    @Override
    public IncomeStatementBase getFillData(IncomeStatementVo statementVo, String fillDate) {
        log.info("incomeStatementlService getFillData start param: {}, fillDate: {}", JSONObject.toJSONString(statementVo), fillDate);
        Cnd cnd = Cnd.NEW();
        SqlExpressionGroup where = cnd.where();
        where.andEquals(IncomeStatementBase::getCompanyId, statementVo.getCompanyId())
                .andEquals(IncomeStatementBase::getFillType, statementVo.getFillType())
                .andEquals(IncomeStatementBase::getIsDelete, false);
        if (StringUtils.isEmpty(fillDate)) {
            fillDate = statementVo.getFillDate();
        }
        where.andEquals(IncomeStatementBase::getFillDate, fillDate);
        IncomeStatementBase base = this.fetch(cnd);
        log.info("incomeStatementlService getFillData res: {}", JSONObject.toJSONString(base));
        return base;
    }
}
